package com.zcc.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zcc.blog.dto.BlogDto;
import com.zcc.blog.dto.BlogDtos;
import com.zcc.blog.dto.CategoryDto;
import com.zcc.blog.dto.CategoryDtos;
import com.zcc.blog.entity.Blog;
import com.zcc.blog.entity.Category;
import com.zcc.blog.entity.TbCategoryBlog;
import com.zcc.blog.mapper.BlogMapper;
import com.zcc.blog.mapper.CategoryMapper;
import com.zcc.blog.mapper.TbCategoryBlogMapper;
import com.zcc.blog.service.BlogService;
import com.zcc.blog.service.CategoryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zcc.blog.service.TbCategoryBlogService;
import com.zcc.blog.untils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zcc
 * @since 2022-09-11
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {

    @Autowired
    TbCategoryBlogService tbCategoryBlogService;
    @Autowired
    BlogService blogService;
    @Autowired
    CategoryMapper categoryMapper;
    @Autowired
    BlogMapper blogMapper;

    /**
     * 将获得的Category封装为CategoryDto
     * @param records
     * @return
     */
    public List<CategoryDto> categoryUtil(List<Category> records){
        List<CategoryDto> categories = new ArrayList<CategoryDto>();
        for (Category record: records) {
            CategoryDto categoryDto = new CategoryDto();
            categoryDto.setId(record.getId());
            categoryDto.setTitle(record.getTitle());
            categoryDto.setUserId(record.getUserId());
            categoryDto.setStatus(record.getStatus());
            QueryWrapper<TbCategoryBlog> eq = new QueryWrapper<TbCategoryBlog>().eq("category_id", record.getId()).eq("status", 0);
            List<TbCategoryBlog> allByCategoryId = tbCategoryBlogService.list(eq);
            List<Long> blogIds = new ArrayList<>();
            for (TbCategoryBlog tbCategoryBlog: allByCategoryId) {
                blogIds.add(tbCategoryBlog.getBlogId());
            }
            categoryDto.setBlogTotal(allByCategoryId.size());
            categoryDto.setBlogIds(blogIds);
            categories.add(categoryDto);
        }
        return categories;
    }

    @Override
    public Result findCategories(Integer currentPage, Integer size, Long id, Integer status) {
        Page page = new Page(currentPage, size);
        QueryWrapper<Category> eq = new QueryWrapper<Category>().eq("user_id", id).eq("status", status);
        IPage pageData = this.page(page, eq);
        List<Category> records = pageData.getRecords();
        int count = this.count(eq);
        List<CategoryDto> categories = categoryUtil(records);
        CategoryDtos categoryDtos = new CategoryDtos();
        categoryDtos.setCategoryDtos(categories);
        categoryDtos.setTotal(count);
        return Result.success(categoryDtos);
    }

    @Override
    public Result getAllCategories(Long id, Integer status) {
        QueryWrapper<Category> eq = new QueryWrapper<Category>().eq("user_id", id).eq("status", status);
        List<Category> list = this.list(eq);
        List<CategoryDto> categories = categoryUtil(list);
        return Result.success(categories);
    }

    @Override
    public Result getBlogsByCategoryId(Integer currentPage, Integer size, Long id) {
        Category category = this.categoryMapper.selectById(id);
        QueryWrapper<TbCategoryBlog> eq = new QueryWrapper<TbCategoryBlog>().eq("category_id", id).eq("status", 0);
        Page page = new Page(currentPage, size);
        IPage pageData = tbCategoryBlogService.page(page, eq);
        List<TbCategoryBlog>  allByCategoryId = pageData.getRecords();
        List<BlogDto> blogDtoList = new ArrayList<>();
        for (TbCategoryBlog tbCategoryBlog: allByCategoryId) {
            Long blogId = tbCategoryBlog.getBlogId();
            Blog blog = blogMapper.selectById(blogId);
            BlogDto blogDto = new BlogDto();
            blogDto.setBlog(blog);
            blogDtoList.add(blogDto);
        }
        BlogDtos blogDtos = new BlogDtos();
        blogDtos.setBlogDtos(blogDtoList);
        int count = tbCategoryBlogService.count(eq);
        blogDtos.setTotal(count);
        return Result.success(blogDtos);
    }

    @Override
    public Result searchCategories(String name, Integer currentPage, Integer size, Long id, Integer status) {
        Page page = new Page(currentPage, size);
        QueryWrapper<Category> eq = new QueryWrapper<Category>().eq("user_id", id).eq("status", status).like("title", name);
        IPage pageData = this.page(page, eq);
        List<Category> records = pageData.getRecords();
        int count = this.count(eq);
        List<CategoryDto> categories = categoryUtil(records);
        CategoryDtos categoryDtos = new CategoryDtos();
        categoryDtos.setCategoryDtos(categories);
        categoryDtos.setTotal(count);
        return Result.success(categoryDtos);
    }

    @Override
    public Result addCategory(Category category) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("title", category.getTitle());
        Collection<Category> categories = this.listByMap(map);
        /**
         * 新增的分类的名称是否重复，
         * 若是重复就新增失败，否者就新增成功
         */
        if (categories.size() == 0) {
            Category c = category;
            c.setStatus(0);
            boolean save = this.save(c);
            if (save) {
                return Result.success(null);
            } else {
                return Result.fail("新增分类失败");
            }
        }
        return Result.fail("已经存在相同的标题，请修改");
    }

    @Override
    public Result deleteCategory(Long id) {
        boolean b = categoryMapper.changeStatus(1, id);
        if (b) {
            // 还需要删除分类下对应的博客
            List<TbCategoryBlog> allByCategoryId = tbCategoryBlogService.findAllByCategoryId(id);
            for (TbCategoryBlog tbCategoryBlog: allByCategoryId) {
                blogService.deleteBlog(tbCategoryBlog.getBlogId());
                tbCategoryBlogService.deleteTbCategoryBlog(tbCategoryBlog.getId());
            }
            return Result.success(null);
        }
        return Result.fail("删除分类失败");
    }

    @Override
    public Result recoverCategory(Long id) {
        boolean b = categoryMapper.changeStatus(0, id);
        if (b) {
            // 还需要恢复分类下对应的博客
            List<TbCategoryBlog> allByCategoryId = tbCategoryBlogService.findAllByCategoryId(id);
            for (TbCategoryBlog tbCategoryBlog: allByCategoryId) {
                blogService.recoverBlog(tbCategoryBlog.getBlogId());
                tbCategoryBlogService.recoverTbCategoryBlog(tbCategoryBlog.getId());
            }
            return Result.success(null);
        }
        return Result.fail("恢复分类失败");
    }

    @Override
    public Result updateCategory(Category category) {
        Category selectById = categoryMapper.selectById(category.getId());
        boolean isCurrentTitle = category.getTitle().equals(selectById.getTitle());
        /**
         * 修改的名称是否为当前的分类的名称，若是就直接修改，
         * 否者就先判断当前修改的分类的名称是否重复，
         * 若是重复就修改失败，否者就修改成功
         */
        if (isCurrentTitle) {
            return Result.success(null);
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("title", category.getTitle());
        Collection<Category> categories = this.listByMap(map);
        if (categories.size() == 0) {
            int update = categoryMapper.updateById(category);
            if (update == 1) {
                return Result.success(null);
            } else {
                return Result.fail("更新分类失败");
            }
        }
        return Result.fail("修改的分类标题重新，请修改");
    }

    @Override
    public Result countCategories(Long id) {
        QueryWrapper<Category> eq = new QueryWrapper<Category>().eq("user_id", id).eq("status", 0);
        int count = this.count(eq);
        return Result.success(count);
    }
}
